//
// CATGL - Cheap Action-game Tool with WebGL.
//
// Copyright 2010, tmasda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

function ActorManager(){}

ActorManager.prototype = {
    // Actorの追加
    addActor: function(actor){
        //this.list.push(actor);
        if (this.top){
            this.tail.next = actor;
            actor.prev = this.tail;
            actor.next = null;
            this.tail = actor;
        } else {
            this.top = actor;
            this.tail = actor;
            actor.prev = null;
            actor.next = null;
        }
    },
    // Actorの削除
    deleteActor: function(actor){
        if (actor.next){
            actor.next.prev = actor.prev;
        } else {
            this.tail = actor.prev;
        }
        if (actor.prev){
            actor.prev.next = actor.next;
        } else {
            this.top = actor.next;
        }
    },
    // 全Actorの描画
    drawAllActor: function(){
        var matrixStack = catGL.matrixStack;
        var shaderManager = catGL.shaderManager;

        // 再帰的に描画するための関数
        function drawChild(childModel){
            var i;
            var childArray = childModel.child;
            // modelの行列のpush
            if (childModel.matrix){
                matrixStack.push(childModel.matrix);
            }
            // shaderへの設定
            shaderManager.setup(childModel);
            // 描画処理
            childModel.drawFunc();

            // 子供の描画
            if (childArray){
                for (i = 0; i < childArray.length; i++){
                    drawChild(childArray[i]);
                }
            }
            // modelの行列のpop
            if (childModel.matrix){
                matrixStack.pop();
            }
        }
        // actorのリストを描画
        var actor = this.top;
        while (actor){
            // Actorとしての行列のpush
            matrixStack.push(actor.matrix);

            // modelの行列のpush
            if (actor.model.matrix){
                matrixStack.push(actor.model.matrix);
            }
            // Armatureで無ければ描画
            if (!actor.model.isArmature){
                // shaderへの設定
                shaderManager.setup(actor.model);
                // 描画処理
                actor.model.drawFunc();
            }
            
            // 子供の描画
            if (actor.model.child){
                var childArray = actor.model.child;
                for (i = 0; i < childArray.length; i++){
                    drawChild(childArray[i]);
                }
            }
            // modelの行列のpop
            if (actor.model.matrix){
                matrixStack.pop();
            }
            // Actorの行列のpop
            matrixStack.pop();

            // 次のActorへ
            actor = actor.next;
        }
    },
    // 全Actorの登録された処理の実行
    execAllActor: function(){
        var actor = this.top;
        while (actor){
            if (actor.exec){
                actor.exec();
            }
            actor = actor.next;
        }
    },
    // 3軸ラインモデルの登録(debug)
    setAxisModel: function(model){
        this.axisModel = model;
    },
    // 全Actorの行列をaxisモデルで表示
    drawAllActorAxis: function(){
        var matrixStack = catGL.matrixStack;
        var shaderManager = catGL.shaderManager;
        var axisModel = this.axisModel;
        shaderManager.setup(axisModel);
        function drawChild(childModel){
            var i;
            var childArray = childModel.child;
            if (childModel.matrix){
                matrixStack.push(childModel.matrix);
            }
            shaderManager.setup(axisModel);
            axisModel.drawFunc();
            if (childArray){
                for (i = 0; i < childArray.length; i++){
                    var child = childArray[i];
                    drawChild(child);
                }
            }
            if (childModel.matrix){
                matrixStack.pop();
            }
        }
        var actor = this.top;
        while (actor){
            matrixStack.push(actor.matrix);
            if (actor.model.matrix){
                matrixStack.push(actor.model.matrix);
            }
            shaderManager.setup(axisModel);
            axisModel.drawFunc();
            
            if (actor.model.child){
                var childArray = actor.model.child;
                for (i = 0; i < childArray.length; i++){
                    var child = childArray[i];
                    drawChild(child);
                }
            }
            if (actor.model.matrix){
                matrixStack.pop();
            }
            matrixStack.pop();
            actor = actor.next;
        }
        //var actor = this.top;
        //while (actor){
        //    //var actor = list[i];
        //    matrixStack.push(actor.matrix);
        //    shaderManager.setup(axisModel);
        //    axisModel.drawFunc();
        //    matrixStack.pop();
        //    actor = actor.next;
        //}
    }
};

ActorManager.create = function()
{
    var actorMan = new ActorManager();
    actorMan.list = [];
    actorMan.top = null;
    actorMan.tail = null;
    return actorMan;
}

function Actor(){}

Actor.create = function(matrix, model){
    var actor = new Actor();
    actor.matrix = matrix;
    actor.model = model;

    return actor;
}
